﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using YABE.Models;
using YABE.Modules;
using YABE.Validators;

namespace YABE.Controllers
{
	[HandleError]
	public class PostsController : Controller
	{
        private Models.IPostDL pd;
		
		public PostsController()
		{
            this.pd = new YABE.Models.PostDL();
		}

        public PostsController(Models.IPostDL pd)
        {
            this.pd = pd;
        }

		#region querying posts

		public ActionResult List()
		{
			List<YABE.Models.Post> posts = pd.GetPosts();
		    posts.Reverse();
			return View("List", ThemeEngine.ViewMasterPage, posts);
		}

		public ActionResult ListYear(int year)
		{

			return View("List", ThemeEngine.ViewMasterPage, pd.GetPosts(year));
		}

		public ActionResult ListMonth(int year, int month)
		{
			return View("List", ThemeEngine.ViewMasterPage, pd.GetPosts(year, month));
		}

		public ActionResult ListDay(int year, int month, int day)
		{
			return View("List", ThemeEngine.ViewMasterPage, pd.GetPosts(year, month, day));
		}

		public ActionResult Single(int year, int month, int day, string title)
		{
			return View("Single", ThemeEngine.ViewMasterPage, pd.GetPost(year, month, day, title));
		}
        
		public ActionResult ListByTag(string tag)
		{
			if (tag.ToLower().Trim() == "uncategorized")
				tag = null;

			return View("List", ThemeEngine.ViewMasterPage, pd.GetPostsByTag(tag));
		}
		#endregion
		
		public ActionResult Index()
		{
			return List();
		}

		public ActionResult About()
		{
			return View("About", ThemeEngine.ViewMasterPage);
		}

		#region post editing
		[Authorize]
		public ActionResult Add()
		{
			return View("Add", ThemeEngine.AdminMasterPage);
		}

		[Authorize]
		[ValidateInput(false)]
		public ActionResult Save(string title, string author, string description, string body, string tags)
		{
			List<Models.Tag> tagList = new List<YABE.Models.Tag>(); 
			List<Models.Post> posts = new List<Models.Post>();
			Models.Post p = new Models.Post();
			p.Author = author;
			p.Title = title;
			p.Description = description;
			p.Body = body;
			p.Created = p.Modified = DateTime.Now;
			p.IsPublic = true;
			p.ShowOnFrontPage = true;
			p.AllowComments = true;

			if (tags != null && tags.Trim().Length > 0)
			{
				tagList = Models.TagDL.AddTags(tags.Split(','));	
			}
			/*Models.YabeDataContext db = new YABE.Models.YabeDataContext();
			db.AddPost(p);*/
			//posts.Add(p);
			this.pd.AddPost(p,tagList);
			return Redirect(Modules.Helpers.WebHelper.SiteRoot + "/Admin/List");
		}
		
		[Authorize]
		[AcceptVerbs("GET")]
		public ActionResult Edit(int id)
		{
		    //as this method needs authorization, all the comments should be loaded
		    return View("Edit", ThemeEngine.AdminMasterPage, pd.GetPostByIdWithUnApprovedComments(id));
		}

	    [Authorize]
		[ActionName("Edit"), AcceptVerbs("POST")]
		[ValidateInput(false)]
		public ActionResult SaveEdit(int id, string title, string author, string description, string body, string tags)
		{
            //as this method needs authorization, all the comments should be loaded
            YABE.Models.Post p = pd.GetPostByIdWithUnApprovedComments(id);
			List<Models.Tag> tagList = new List<YABE.Models.Tag>();
			
			p.Author = author;
			p.Title = title;
			p.Description = description;
			p.Body = body;
			p.Modified = DateTime.Now;
			p.IsPublic = true;
			p.ShowOnFrontPage = true;
			p.AllowComments = true;
			p.PostTags.Clear();

			if (tags != null && tags.Trim().Length > 0)
			{
				tagList = Models.TagDL.AddTags(tags.Split(','));
			}

            try
            {
                List<RuleViolation> issues = p.GetRuleViolations();
                if(issues.Count>0)
                {
                    throw new BLValidationException(issues);
                }
                this.pd.UpdatePost(p, tagList);
                //now we have check the comments
                //TODO: Implement check approval

            }
            catch(BLValidationException err)
            {
                TempData["Message"] = "Post update problem occured.";
                foreach(var issue in err.issues)
                {
                    ViewData.ModelState.AddModelError( issue.PropertyName
						,issue.ErrorMessage);
                }
                return View("Edit", ThemeEngine.AdminMasterPage, pd.GetPostByIdWithUnApprovedComments(id));
            }

			return Redirect(Modules.Helpers.WebHelper.SiteRoot + "/Admin/List");
		}
		
		[Authorize]
		public ActionResult Update(string title, string author, string description, string body)
		{
			Models.Post p = new Models.Post();
			p.Author = author;
			p.Title = title;
			p.Description = description;
			p.Body = body;
			p.Created = p.Modified = DateTime.Now;
			p.IsPublic = true;
			p.ShowOnFrontPage = true;
			p.AllowComments = true;

			//db.UpdatePost(p);

			return RedirectToAction("List");
		}
		#endregion

        #region Comments Section
        public ActionResult AddComment(int PostID,string Name, string Email, string Url, string Comments)
        {
			bool approveComments = bool.Parse(ConfigurationManager.AppSettings["ApproveComments"]);
            string clientIP = this.HttpContext.Request.Params["REMOTE_ADDR"];
            DateTime Created = DateTime.Now;
            Name = Server.HtmlEncode(Name);
            Email = Server.HtmlEncode(Email);
            Url = Server.UrlDecode(Url);
            Comments = Server.HtmlEncode(Comments);

            
			// akismet check
			Subkismet.Akismet<Subkismet.Comment> akismet = Subkismet.Akismet<Subkismet.Comment>.CreateSimpleAkismet(
				ConfigurationManager.AppSettings["AkismetKey"], 
				new Uri(Modules.Helpers.WebHelper.SiteRoot));
			
			Subkismet.Comment comment = new Subkismet.Comment(System.Net.IPAddress.Parse(clientIP)
				, Request.UserAgent);

			try
			{
				comment.AuthorUrl = new Uri(Url);
			}
			catch 
			{ 
				Url = null; 
			}

			comment.Author = Name;
			comment.CommentType = "comment";
			comment.Content = Comments;
			bool isSpam = akismet.IsSpam(comment);

			if (isSpam)
			{
				TempData["Message"] = "Spam detected!";
				Post post = pd.GetPostById(PostID);
				return View("Single", ThemeEngine.ViewMasterPage, post);
			}

            try
            {
				Comment newComment = new Comment();
				newComment.Author = Name;
				newComment.Email = Email;
				newComment.Created = Created;
				newComment.Comments = Comments;
				newComment.ClientIP = clientIP;
				newComment.Url = Url;
				newComment.PostID = PostID;
				newComment.IsApproved = !approveComments;

                List<RuleViolation> issues = newComment.GetRuleViolations();
                if (issues.Count > 0)
                {
                    throw new BLValidationException(issues);
                }
            }
            catch(BLValidationException ex)
            {
                //when we go back to the browser , we dont want the user lose his entered data
                TempData["Message"] = "Problem occured while adding comment.";
                TempData["Name"] = Request.Form["Name"];
                TempData["Email"] = Request.Form["Email"];
                TempData["Url"] = Request.Form["Url"];
                TempData["Comments"] = Request.Form["Comments"];
                foreach(var issue in ex.issues)
                {
                    ViewData.ModelState.AddModelError(issue.PropertyName,issue.ErrorMessage);
                }
                
                //preparing for redirectroute to Single(int year, int month, int day, string title)
                Post post = pd.GetPostById(PostID);
                string title = post.Title.Replace(' ', '-');
                return View("Single", ThemeEngine.ViewMasterPage, post);
                
            }
            //now add the comment
            pd.AddComment(PostID, Name, Email, Url, Comments, Created, !approveComments, clientIP, Created);
            Post newpost = pd.GetPostById(PostID);
            //tell the user comment is added
			if (approveComments)
	            TempData["Message"] = "Comment is added. However, it has to be approved first.";
			else
				TempData["Message"] = "Thank You!";

            return View("Single", ThemeEngine.ViewMasterPage, newpost);

        }

	    #endregion
    }
}
